﻿using System;
using System.Linq;
using System.Xml.Linq;
using UtfprLibrary.Helpers;
using UtfprLibrary.ComponentModel;
using UtfprLibrary.Exceptions;

namespace UtfprLibrary.Configurations.DesignTime {
    /// <summary>
    /// TODO
    /// </summary>
    public class UtfprSection : UtfprSectionBase {
        #region Security

        private SecurityElement _security;
        /// <summary>
        /// TODO
        /// </summary>
        /// <exception cref="UtfprLibrary.Exceptions.UtfprConfigurationsException">Thrown when an exception occurs.</exception>
        public SecurityElement Security {
            get {
                try {
                    if (_security == null) {
                        _security = new SecurityElement(getModuleIdAttribute(), getQueryAttribute(), getBranchAttribute(), getTypeAttribute());
                    }
                    return _security;
                } catch (Exception ex) {
                    throw new UtfprConfigurationsException(Properties.Resources.Configurations_DesignTime_UtfprSection_ExMsg_Security, ex);
                }
            }
        }

        #region Private

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        private static XElement getUtfprTag() {
            XDocument config = GetAppConfigDocument();

            var utfpr = config.Root.Elements().Where(e => e.Name.LocalName == "utfpr").FirstOrDefault();
            if (utfpr == null) { throw new ArgumentException("Tag utfpr não encontrada."); }

            return utfpr;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        private static XElement getSecurityTag() {
            var security = getUtfprTag().Elements().Where(e => e.Name.LocalName == "security").FirstOrDefault();
            if (security == null) { throw new ArgumentException("Tag security não encontrada."); }
            return security;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        private static string getModuleIdAttribute() {
            var moduleI = getSecurityTag().Attributes().Where(e => e.Name.LocalName == "moduleId").FirstOrDefault();
            if (moduleI == null) { throw new ArgumentException("Atributo moduleId não encontrado."); }
            return moduleI.Value;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        private static string getBranchAttribute() {
            var branch = getSecurityTag().Attributes().Where(e => e.Name.LocalName == "branch").FirstOrDefault();
            if (branch == null) { throw new ArgumentException("Atributo branch não encontrado."); }
            return branch.Value;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        private string getQueryAttribute() {
            var query = getSecurityTag().Attributes().Where(e => e.Name.LocalName == "query").FirstOrDefault();
            if (query == null) { throw new ArgumentException("Atributo query não encontrado."); }
            return query.Value;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        private static TypeElement getTypeAttribute() {
            var type = getSecurityTag().Attributes().Where(e => e.Name.LocalName == "type").FirstOrDefault();
            if (type == null) { throw new ArgumentException("Atributo type não encontrado."); }

            var element = new TypeElement(
                getTypeName(type.Value), getAssemblyName(type.Value));

            return element;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <param name="typeValue"></param>
        /// <returns></returns>
        private static string getAssemblyName(string typeValue) {
            return typeValue.Split(',')[1].Trim() + ".dll";
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <param name="typeValue"></param>
        /// <returns></returns>
        private static string getTypeName(string typeValue) {
            return typeValue.Split(',')[0].Trim();
        }

        #endregion

        #endregion

        /// <summary>
        /// TODO: This method just knows what to do for 'Debug|x86', and should be corrected in the future.
        /// TODO: Another issue is that it presumes this folder structure convention
        ///  - directory:\UtfprLibraryPath\src\UtfprLibrary.WindowsForms
        ///  - directory:\UtfprLibraryPath\build\UtfprLibrary.WindowsForms\bin\Debug
        /// </summary>
        /// <exception cref="UtfprLibrary.Exceptions.UtfprConfigurationsException">Thrown when an exception occurs.</exception>
        public string ActiveProjectDebugPath {
            get {
                try {
                    XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
                    XDocument csprojDocument = XDocument.Load(GetActiveProjectPath());
                    XElement projectElement = csprojDocument.Element(msbuild + "Project");
                    XElement propertyGroupElement = projectElement.Elements(msbuild + "PropertyGroup")
                        .Single(p => p
                            .Attributes()
                            .Where(att => att.Name == "Condition" && att.Value == Properties.Resources.Configurations_DesignTime_UtfprSection_Const_UtfprConfigurationPlatform)
                            .Count() > 0
                        );
                    XElement outputPathElement = propertyGroupElement.Elements(msbuild + "OutputPath").Single();

                    //<OutputPath>..\..\build\UtfprLibrary.WindowsForms\bin\Debug\</OutputPath>

                    //outputPathValue = "..\..\build\UtfprLibrary.WindowsForms\bin\Debug\"
                    string currentOutputPath = outputPathElement.Value;

                    //outputPathValue = "build\UtfprLibrary.WindowsForms\bin\Debug\"
                    currentOutputPath = currentOutputPath.Remove(0, 6);

                    //activePath = directory:\projectFolder\projectSubFolder\projectName
                    string activeProjectDebugPath = PathHelper.PathRemove(GetActiveProjectDirectoryPath(), 2);

                    //activePath = directory:\project\build\UtfprLibrary.WindowsForms\bin\Debug\
                    activeProjectDebugPath += "\\" + currentOutputPath;
                    return activeProjectDebugPath;
                } catch (Exception ex) {
                    throw new UtfprConfigurationsException(Properties.Resources.Configurations_DesignTime_UtfprSection_ExMsg_ActiveProjectDebugPath, ex);
                }
            }
        }
    }
}
